﻿Imports UCBase.Plug
Imports Microsoft.VisualBasic.PowerPacks
Imports System
Imports System.Threading
Imports System.Windows.Forms
Imports System.Drawing

Public Class LineRouter
    Inherits Control
    Implements I_EditMode

    Private sp As Point
    Private SelP As Integer
    Private L1 As Integer
    Private L2 As Integer
    Private LA As PatternLineShape
    Private LB As PatternLineShape
    Private M_P1 As Plug
    Private M_P2 As Plug
    Private M_S1 As Socket
    Private M_S2 As Socket
    Private M_Parent As DiagramPanel
    Private M_LS1 As PatternLineShape
    Private M_LS2 As PatternLineShape
    Private M_CS1 As OvalShape
    Private M_CS2 As OvalShape
    Private M_CW As PatternLineShape
    Private PointCol As New Collection
    Private LineCol As New Collection
    'Private LineColB As New Collection
    Private OvalCol As New Collection

    Private M_Last_P1 As Point
    Private M_Last_P2 As Point
    Private M_Last_MousePos As Point
    Public Event Disconnect(ByVal sender As Object)

    Private M_Edit As Boolean = True

    Dim GlobalCanvas As New ShapeContainer


    Private Enum dir
        up = 1
        down = 2
        left = 3
        right = 4
    End Enum
    Public Sub RePosition()
        M_P1.SetCenter(M_S1.CenterPoint)
        M_P2.SetCenter(M_S2.CenterPoint)

        M_LS1.StartPoint = M_P1.GetLinePoint
        If M_P1.ExitTo = Exit_Side.To_Bottom Then
            M_LS1.Y2 = M_LS1.Y1 + 15
            M_LS1.X2 = M_LS1.X1
        End If
        If M_P1.ExitTo = Exit_Side.To_Top Then
            M_LS1.Y2 = M_LS1.Y1 - 15
            M_LS1.X2 = M_LS1.X1
        End If
        If M_P1.ExitTo = Exit_Side.To_Left Then
            M_LS1.Y2 = M_LS1.Y1
            M_LS1.X2 = M_LS1.X1 - 15
        End If
        If M_P1.ExitTo = Exit_Side.To_Right Then
            M_LS1.Y2 = M_LS1.Y1
            M_LS1.X2 = M_LS1.X1 + 15
        End If
        M_CS1.Left = M_LS1.X2 - 4
        M_CS1.Top = M_LS1.Y2 - 4
        M_CS1.Width = 8
        M_CS1.Height = 8
        LA.StartPoint = M_LS1.EndPoint

        M_LS2.StartPoint = M_P2.GetLinePoint
        If M_P2.ExitTo = Exit_Side.To_Bottom Then
            M_LS2.Y2 = M_LS2.Y1 + 15
            M_LS2.X2 = M_LS2.X1
        End If
        If M_P2.ExitTo = Exit_Side.To_Top Then
            M_LS2.Y2 = M_LS2.Y1 - 15
            M_LS2.X2 = M_LS2.X1
        End If
        If M_P2.ExitTo = Exit_Side.To_Left Then
            M_LS2.Y2 = M_LS2.Y1
            M_LS2.X2 = M_LS2.X1 - 15
        End If
        If M_P2.ExitTo = Exit_Side.To_Right Then
            M_LS2.Y2 = M_LS2.Y1
            M_LS2.X2 = M_LS2.X1 + 15
        End If
        M_CS2.Left = M_LS2.X2 - 4
        M_CS2.Top = M_LS2.Y2 - 4
        M_CS2.Width = 8
        M_CS2.Height = 8
        LB.EndPoint = M_LS2.EndPoint
        M_Parent.Refresh()
    End Sub
    Public Property Plug1() As Plug
        Get
            Return M_P1
        End Get
        Set(ByVal value As Plug)
            M_P1 = value
            DrawStart(M_P1, 1)
        End Set
    End Property
    Public Property Plug2() As Plug
        Get
            Return M_P2
        End Get
        Set(ByVal value As Plug)
            M_P2 = value
            DrawStart(M_P2, 2)
        End Set
    End Property
    Public Property Socket1() As Socket
        Get
            Return M_S1
        End Get
        Set(ByVal value As Socket)
            M_S1 = value
        End Set
    End Property
    Public Property Socket2() As Socket
        Get
            Return M_S2
        End Get
        Set(ByVal value As Socket)
            M_S2 = value
        End Set
    End Property
    Public Sub DrawWire()
        GlobalCanvas.Parent = M_Parent
        CreatePlug1()
        CreatePlug2()
        M_LS1 = DrawStart(M_P1, 1)
        M_LS2 = DrawStart(M_P2, 2)
        PointCol.Clear()
        Dim Mx As Integer
        Dim Myy As Integer
        If M_LS1.X2 > M_LS2.X2 Then
            Mx = ((M_LS1.X2 - M_LS2.X2) / 2) + M_LS2.X2
        Else
            Mx = ((M_LS2.X2 - M_LS1.X2) / 2) + M_LS1.X2
        End If

        If M_LS1.Y2 > M_LS2.Y2 Then
            Myy = ((M_LS1.Y2 - M_LS2.Y2) / 2) + M_LS2.Y2
        Else
            Myy = ((M_LS2.Y2 - M_LS1.Y2) / 2) + M_LS1.Y2
        End If
        Dim MP As New Point(Mx, Myy)
        Dim H As New MoveHandle
        H.Visible = False
        M_Parent.Controls.Add(H)
        H.Center = MP
        PointCol.Add(H)
        AddHandler H.Moved, AddressOf HandleMoved
        AddHandler H.MouseEnter, AddressOf OvalMouseEnter
        AddHandler H.MouseUp, AddressOf MoveMouseUp
        AddHandler H.Remove, AddressOf HandleRemove
        Route2()
        M_P1.Visible = True
        M_P2.Visible = True
        M_LS1.Visible = True
        M_LS2.Visible = True
        M_CS1.Visible = True
        M_CS2.Visible = True
        For Each L As PatternLineShape In LineCol
            L.Visible = True
        Next
        For Each C As OvalShape In OvalCol
            C.Visible = True
        Next
        For Each M As MoveHandle In PointCol
            M.Visible = True
            M.BringToFront()
        Next
        Dim Pan As DiagramPanel = M_Parent

    End Sub
    Private Sub MoveMouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        LoLite()
    End Sub

    Public Sub Route2()

        For Each L As PatternLineShape In LineCol
            L.Dispose()
        Next
        LineCol.Clear()

        For Each O As OvalShape In OvalCol
            O.Dispose()
        Next
        OvalCol.Clear()

        Dim M_Con As New ContextMenuStrip
        Dim I As New ToolStripMenuItem("Add Point")
        AddHandler I.Click, AddressOf AddPoint
        M_Con.Items.Add(I)
        Dim DC As New ToolStripMenuItem("Disconnect")
        M_Con.Items.Add(DC)
        AddHandler DC.Click, AddressOf PlugDisconnect

        Dim L1 As New PatternLineShape
        L1.Visible = False
        'GlobalCanvas.Parent = M_Parent
        L1.Parent = GlobalCanvas
        L1.BorderWidth = 8
        L1.BorderColor = M_P1.SocketColor
        L1.IdentColor = M_P1.SocketColorB
        L1.StartPoint = M_LS1.EndPoint
        Dim E1 As MoveHandle = PointCol.Item(1)
        L1.EndPoint = E1.Center
        LA = L1
        LineCol.Add(L1)
        AddHandler L1.MouseEnter, AddressOf OvalMouseEnter
        AddHandler L1.MouseClick, AddressOf LineMouseClick
        L1.ContextMenuStrip = M_Con
        If PointCol.Count > 1 Then
            Dim Cc As Integer
            For Cc = 1 To PointCol.Count - 1
                Dim H1 As MoveHandle = PointCol.Item(Cc)
                Dim H2 As MoveHandle = PointCol.Item(Cc + 1)
                'Dim Ncanvas As New ShapeContainer
                Dim L As New PatternLineShape
                L.Visible = False
                'Ncanvas.Parent = M_Parent
                L.Parent = GlobalCanvas
                L.BorderWidth = 8
                L.BorderColor = M_P1.SocketColor
                L.IdentColor = M_P1.SocketColorB
                L.BringToFront()
                L.StartPoint = H1.Center
                L.EndPoint = H2.Center
                LineCol.Add(L)
                'L.Enabled = False
                AddHandler L.MouseEnter, AddressOf OvalMouseEnter
                AddHandler L.MouseClick, AddressOf LineMouseClick
                L.ContextMenuStrip = M_Con
            Next
        End If

        'Dim canvas2 As New ShapeContainer
        Dim L2 As New PatternLineShape
        L2.Visible = False
        LB = L2
        'globalcanvas.Parent = M_Parent
        L2.Parent = GlobalCanvas
        L2.BorderWidth = 8
        L2.BorderColor = M_P1.SocketColor
        L2.IdentColor = M_P1.SocketColorB
        L2.BringToFront()
        L2.EndPoint = M_LS2.EndPoint
        Dim E2 As MoveHandle = PointCol.Item(PointCol.Count)
        L2.StartPoint = E2.Center
        LineCol.Add(L2)
        AddHandler L2.MouseEnter, AddressOf OvalMouseEnter
        AddHandler L2.MouseClick, AddressOf LineMouseClick
        L2.ContextMenuStrip = M_Con
        'L2.Enabled = False

        For Each P As MoveHandle In PointCol
            'Dim CCanvas As New ShapeContainer
            Dim C As New OvalShape
            C.Visible = False
            'CCanvas.Parent = M_Parent
            C.Parent = GlobalCanvas
            C.FillStyle = FillStyle.Solid
            C.Left = P.Center.X - 4
            C.Top = P.Center.Y - 4
            C.Width = 8
            C.Height = 8
            C.FillColor = M_P1.SocketColor
            C.BorderColor = M_P1.SocketColor
            C.BringToFront()
            OvalCol.Add(C)
            AddHandler C.MouseEnter, AddressOf OvalMouseEnter
        Next
        For Each lin As PatternLineShape In LineCol
            lin.Visible = True
        Next
    End Sub

    Private Sub HandleMoved(ByVal OldPoint As Point, ByVal NewPoint As System.Drawing.Point)
        For Each L As PatternLineShape In LineCol
            If L.StartPoint = OldPoint Then L.StartPoint = NewPoint
            If L.EndPoint = OldPoint Then L.EndPoint = NewPoint
            If L.StartPoint.X = L.EndPoint.X Then
                L.BorderColor = Color.Purple
                L.IdentColor = Color.Purple
            Else
                If L.StartPoint.Y = L.EndPoint.Y Then
                    L.BorderColor = Color.Purple
                    L.IdentColor = Color.Purple
                Else
                    L.BorderColor = M_P1.SocketColor
                    L.IdentColor = M_P1.SocketColorB
                End If
            End If
            L.Refresh()
        Next
        For Each O As OvalShape In OvalCol
            If O.Left + 4 = OldPoint.X And O.Top + 4 = OldPoint.Y Then
                O.Left = NewPoint.X - 4
                O.Top = NewPoint.Y - 4
            End If
            O.Refresh()
        Next
        M_CS1.Refresh()
        M_CS2.Refresh()
        M_LS1.Refresh()
        M_LS2.Refresh()
        'M_Parent.Refresh()
    End Sub
    Private Sub OvalMouseEnter(ByVal sender As Object, ByVal e As System.EventArgs)
        If TypeOf sender Is PatternLineShape Then
            Dim L As PatternLineShape = sender
            M_Last_P1 = L.StartPoint
            M_Last_P2 = L.EndPoint
            Dim A As Integer = FindPoint(M_Last_P1)
            Dim B As Integer = FindPoint(M_Last_P2)
        End If
    End Sub
    Private Sub LineMouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        If e.Button = Windows.Forms.MouseButtons.Right Then
            M_Last_MousePos = M_Parent.PointToClient(Control.MousePosition)
        End If
    End Sub
    Private Sub LoLite()
        For Each L As PatternLineShape In LineCol
            L.BorderColor = M_S1.SocketColor
            L.IdentColor = Plug1.SocketColorB
            L.Refresh()
        Next
        For Each O As OvalShape In OvalCol
            O.FillColor = M_S1.SocketColor
            O.BorderColor = M_S1.SocketColor
            O.Refresh()
        Next
        M_Parent.Refresh()
    End Sub
    Private Sub Findlines(ByVal Original As Point)
        For c = 1 To LineCol.Count
            Dim L As PatternLineShape = LineCol.Item(c)
            If L.X1 = Original.X Or L.Y1 = Original.Y Then
                L1 = c
            End If
            If L.X2 = Original.X Or L.Y2 = Original.Y Then
                L2 = c
            End If
        Next

    End Sub
    Private Function Findline(ByVal Original As Point)
        For c = 1 To LineCol.Count
            Dim L As PatternLineShape = LineCol.Item(c)
            If L.X1 = Original.X Or L.Y1 = Original.Y Then
                Return c
            End If
            If L.X2 = Original.X Or L.Y2 = Original.Y Then
                Return c
            End If
        Next
        Return -1
    End Function
    Private Function FindPoint(ByVal Original As Point) As Integer
        For c = 1 To PointCol.Count
            Dim p As MoveHandle = PointCol.Item(c)
            If p.Center.X = Original.X And p.Center.Y = Original.Y Then
                Return c
            End If
        Next
        Return -1
    End Function
    Private Function Getdir(ByVal L As PatternLineShape) As dir
        If L.X1 = L.X2 And L.Y1 < L.Y2 Then Return dir.down
        If L.X1 = L.X2 And L.Y1 > L.Y2 Then Return dir.up
        If L.X1 > L.X2 And L.Y1 = L.Y2 Then Return dir.right
        If L.X1 < L.X2 And L.Y1 = L.Y2 Then Return dir.left
    End Function
    Private Function DrawStart(ByVal P As Plug, ByVal CC As Integer) As PatternLineShape
        Dim L As New PatternLineShape
        'GlobalCanvas.Parent = M_Parent
        L.Visible = False
        L.Parent = GlobalCanvas
        L.BorderWidth = 8
        L.BorderColor = P.SocketColor
        L.IdentColor = P.SocketColorB
        L.StartPoint = P.GetLinePoint
        If P.ExitTo = Exit_Side.To_Bottom Then
            L.Y2 = L.Y1 + 15
            L.X2 = L.X1
        End If
        If P.ExitTo = Exit_Side.To_Top Then
            L.Y2 = L.Y1 - 15
            L.X2 = L.X1
        End If
        If P.ExitTo = Exit_Side.To_Left Then
            L.Y2 = L.Y1
            L.X2 = L.X1 - 15
        End If
        If P.ExitTo = Exit_Side.To_Right Then
            L.Y2 = L.Y1
            L.X2 = L.X1 + 15
        End If
        Dim C As New OvalShape
        C.Visible = False
        C.Parent = GlobalCanvas
        C.FillStyle = FillStyle.Solid
        C.Left = L.X2 - 4
        C.Top = L.Y2 - 4
        C.Width = 8
        C.Height = 8
        C.FillColor = P.SocketColor
        C.BorderColor = P.SocketColor
        C.BringToFront()

        If CC = 1 Then
            M_CS1 = C
        Else
            M_CS2 = C
        End If

        Return L
    End Function
    Public Sub CreatePlug1()
        Dim X As New Plug
        GetBaseForm()
        M_Parent.Controls.Add(X)
        X.SocketType = M_S1.SocketType
        X.ExitTo = M_S1.ExitTo
        X.SetCenter(M_S1.CenterPoint)
        X.BringToFront()
        AddHandler X.Disconnect, AddressOf PlugDisconnect
        X.Visible = False
        M_P1 = X
        M_P1.Refresh()
    End Sub
    Public Sub CreatePlug2()
        Dim Y As New Plug
        GetBaseForm()
        M_Parent.Controls.Add(Y)
        Y.SocketType = M_S2.SocketType
        Y.ExitTo = M_S2.ExitTo
        Y.SetCenter(M_S2.CenterPoint)
        Y.BringToFront()
        AddHandler Y.Disconnect, AddressOf PlugDisconnect
        Y.Visible = False
        M_P2 = Y
        M_P2.Refresh()
    End Sub
    Private Sub GetBaseForm()

        If TypeOf M_S1.Parent Is DiagramPanel Then
            M_Parent = M_S1.Parent
            'Exit Sub
        End If
        If TypeOf M_S1.Parent.Parent Is DiagramPanel Then
            M_Parent = M_S1.Parent.Parent
            'Exit Sub
        End If
        If TypeOf M_S1.Parent.Parent.Parent Is DiagramPanel Then
            M_Parent = M_S1.Parent.Parent.Parent
        End If
        If M_Parent.Controls.Contains(GlobalCanvas) = False Then M_Parent.Controls.Add(GlobalCanvas)
    End Sub
    Private Sub AddPoint(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Dim H As New MoveHandle
        M_Parent.Controls.Add(H)
        H.Center = M_Last_MousePos
        H.Visible = True
        H.BringToFront()
        Dim A As Integer = FindPoint(M_Last_P1)
        Dim B As Integer = FindPoint(M_Last_P2)
        If A = -1 Or B = -1 Then
            If A = -1 Then
                PointCol.Add(H, , 1)
                ' Debug.Print("A:-1 B:1 -->" & PointCol.Count)

            End If
            If B = -1 Then
                PointCol.Add(H)
                'Debug.Print("A:>=1 B:-1 -->" & PointCol.Count)
            End If
        Else
            If A < B Then
                PointCol.Add(H, , B)
                'Debug.Print("A < B -->" & PointCol.Count)
            End If
            If A > B Then
                PointCol.Add(H, , A)
                'Debug.Print("A > B -->" & PointCol.Count)
            End If
        End If
        AddHandler H.Moved, AddressOf HandleMoved
        AddHandler H.MouseEnter, AddressOf OvalMouseEnter
        AddHandler H.MouseUp, AddressOf MoveMouseUp
        AddHandler H.Remove, AddressOf HandleRemove
        Route2()
        M_P1.Visible = True
        M_P2.Visible = True
        M_LS1.Visible = True
        M_LS2.Visible = True
        M_CS1.Visible = True
        M_CS2.Visible = True
        For Each L As PatternLineShape In LineCol
            L.Visible = True
        Next
        For Each C As OvalShape In OvalCol
            C.Visible = True
        Next
        For Each M As MoveHandle In PointCol
            M.Visible = True
            M.BringToFront()
        Next
    End Sub
    Private Sub HandleRemove(ByVal sender As Object)
        If PointCol.Count > 1 Then
            Dim H As MoveHandle = sender
            Dim i As Integer = FindPoint(H.Center)
            PointCol.Remove(i)
            H.Dispose()
            Route2()
        End If
    End Sub
    Private Sub PlugDisconnect()
        RaiseEvent Disconnect(Me)
    End Sub
    Public Shadows Sub Dispose()
        For Each L As PatternLineShape In LineCol
            L.Dispose()
        Next
        For Each O As OvalShape In OvalCol
            O.Dispose()
        Next
        For Each M As MoveHandle In PointCol
            M.Dispose()
        Next
        M_CS1.Dispose()
        M_CS2.Dispose()
        M_LS1.Dispose()
        M_LS2.Dispose()
        M_P1.Dispose()
        M_P2.Dispose()
        M_S1.Refresh()
        M_S2.Refresh()
        M_Parent.Refresh()
    End Sub
    Public Function GetPoints() As String
        Dim S As String = ""
        Dim Cc As Integer
        For Cc = 1 To PointCol.Count
            Dim P As MoveHandle = PointCol.Item(Cc)
            S = S & P.Center.ToString & ":"
        Next
        Return S
    End Function
    Public Sub AddPoints(ByVal Points As String)
        If Points.Contains(":") Then
            Dim OH As MoveHandle = PointCol.Item(1)
            OH.Dispose()
            PointCol.Clear()
            Dim Ps As String()
            Ps = Points.Split(":")
            For Each P In Ps
                If P > "" Then
                    Dim xy As String()
                    xy = P.Split(",")
                    Dim X As Integer = Val(xy(0).Substring(3))
                    Dim Y As Integer = Val(xy(1).Substring(2))
                    Debug.Print("Point:" & X.ToString & ":" & Y.ToString)
                    Dim H As New MoveHandle
                    M_Parent.Controls.Add(H)
                    H.Center = New Point(X, Y)

                    H.Visible = True
                    H.BringToFront()
                    PointCol.Add(H)
                    AddHandler H.Moved, AddressOf HandleMoved
                    AddHandler H.MouseEnter, AddressOf OvalMouseEnter
                    AddHandler H.MouseUp, AddressOf MoveMouseUp
                    AddHandler H.Remove, AddressOf HandleRemove
                End If
            Next
            Route2()
            M_P1.Visible = True
            M_P2.Visible = True
            M_LS1.Visible = True
            M_LS2.Visible = True
            M_CS1.Visible = True
            M_CS2.Visible = True
            For Each L As PatternLineShape In LineCol
                L.Visible = True
            Next
            For Each C As OvalShape In OvalCol
                C.Visible = True
            Next
            For Each M As MoveHandle In PointCol
                M.Visible = True
                M.BringToFront()
            Next
        End If
    End Sub

    Public Sub SetEditMode(ByVal Mode As Diagram.EditMode) Implements I_EditMode.SetEditMode
        If Mode = Diagram.EditMode.Locked Then
            For Each L As PatternLineShape In LineCol
                'L.ContextMenuStrip.Enabled = False
            Next
            For Each O As OvalShape In OvalCol
                'O.ContextMenuStrip.Enabled = False
            Next
            For Each H As MoveHandle In PointCol
                H.Visible = False
                'H.BringToFront()
            Next
        Else
            For Each L As PatternLineShape In LineCol
                'L.ContextMenuStrip.Enabled = True
            Next
            For Each O As OvalShape In OvalCol
                ' O.ContextMenuStrip.Enabled = True
            Next
            For Each H As MoveHandle In PointCol
                H.Visible = True
                H.BringToFront()
            Next
        End If
    End Sub

    Public Sub New()

    End Sub
End Class
